home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-09-25 | 19.5 KB | 978 lines | [TEXT/CWIE] |
- // COPYRIGHT 1994 A.D. Software, All rights reserved
-
- // OOFILE database field-related classes
- // see also oof4.cpp
-
- #include "oof2.hpp"
- #include "oof3.hpp"
- #include "oofquery.hpp"
- #include "oofrel.hpp"
-
- // -------------------------------------------------------
- // d b F i e l d
- // -------------------------------------------------------
-
-
- dbField::dbField() :
- mIndexOptions(kNotIndexed)
- {
- dbTable::sCurrentlyConstructing->attachfield(this);
- }
-
-
- dbField::dbField(const OOF_IndexOptions indexOptions) :
- mIndexOptions(indexOptions)
- {
- dbTable::sCurrentlyConstructing->attachfield(this);
- }
-
-
- dbField::dbField(const char *fieldName) :
- mIndexOptions(kNotIndexed),
- mFieldName(fieldName)
- {
- dbTable::sCurrentlyConstructing->attachfield(this);
- }
-
-
- dbField::dbField(const char *fieldName, const OOF_IndexOptions indexOptions) :
- mIndexOptions(indexOptions),
- mFieldName(fieldName)
- {
- dbTable::sCurrentlyConstructing->attachfield(this);
- }
-
-
- dbField::dbField(const dbField& rhs) :
- mBackend(0),
- mTable(0),
- mFieldNumber(rhs.mFieldNumber),
- mIndexOptions(rhs.mIndexOptions),
- mFieldName(rhs.mFieldName)
- {
- #ifdef OOF_Debug
- validateDatabaseState();
- #endif
- if(mRelationChain) { // must be copying a related field, probably a temp copy from a view
- mTable = rhs.mTable;
- mBackend = rhs.mBackend;
- }
- else // normal copy
- {
- dbTable* theTable = dbTable::sCurrentlyConstructing;
- theTable->attachfield(this);
- }
- }
-
- unsigned int dbField::fieldEditLen() const
- {
- if (fieldType()==charField)
- return fieldLen();
- else
- if (fieldType()==textField)
- return 20;
- else
- return 10;
- }
-
-
- const void* dbField::binaryContents()
- {
- validateContextInCaseRelated();
- return mBackend->getFieldReadFrom(mFieldNumber);
- }
-
-
- dbTable* dbField::fieldTable() const
- {
- return mTable;
- }
-
-
- unsigned int dbField::countSegments() const
- {
- if (mIndexOptions==kNotIndexed)
- return 0;
- else
- return 1; // overridden for compound keys
- }
-
-
- bool dbField::fieldIsBlob() const
- {
- return false;
- }
-
-
- bool dbField::fieldIsBinary() const
- {
- return true;
- }
-
-
- bool dbField::fieldIsVirtual() const
- {
- return false;
- }
-
-
- bool dbField::fieldIsIndexed() const
- {
- return mIndexOptions!=kNotIndexed;
- }
-
-
- bool dbField::fieldIsUniqueIndexed() const
- {
- return mIndexOptions==kIndexNoDups;
- }
-
-
- char *dbField::copyAsChars()
- {
- ostrstream oss;
- extract(oss);
- oss << ends;
- #ifdef _RTLDLL // Borland use this to indicate runtime lib in DLL which may mean different allocator
- char* s = oss.str(); // can't just return this - causes crash on delete[]
- long sLen = strlen(s);
- char* ret = new char[sLen+1];
- assert(ret);
- strncpy(ret, s, sLen);
- ret[sLen]='\0';
- oss.rdbuf()->freeze(0); // leave buffer for stream to delete
- return ret;
- #else
- return oss.str();
- #endif
- }
-
-
- void dbField::extract(ostream& os)
- {
- os << "";
- }
-
-
- bool dbField::insert(istream& is, char fieldSep, char recSep)
- {
- char c;
- while (is.good()) {
- is >> c;
- if ((c==fieldSep) || (c==recSep)) {
- is.putback(c); // put the separator back so the caller knows what kind we hit
- return true; // OK - hit a separator
- }
- }
- return false; // fell through without hitting separator
- }
-
-
- void dbField::describe(ostream& os)
- {
- if (mFieldName.isEmpty())
- os << "Un-named field";
- else
- os << "field: " << mFieldName;
- os << " is field type: " << fieldType() << endl;
- if (fieldIsIndexed())
- os << " has indexing: " << fieldIndexOptions() << endl;
- }
-
-
- void dbField::validateContextInCaseRelated()
- {
- #ifdef OOF_Debug
- validateDatabaseState();
- #endif
- if (mRelationChain)
- mRelationChain->validateContext();
- }
-
-
- dbField* dbField::GetRelatedFieldOrUs()
- {
- if (ConsumePossibleRelationChain()) {
- dbRelChain* tempChain = mRelationChain;
- mRelationChain = 0; // clear it, the clone field owns it
- tempChain = tempChain->buildChain();
- return tempChain->getFinalField(mFieldNumber);
- }
- else
- return this;
- }
-
-
- // -------------------------------------------------------
- // d b F i x e d B i n a r y
- // -------------------------------------------------------
- OOF_fieldTypes dbFixedBinary::fieldType() const
- {
- return fixedBinaryField;
- }
-
-
- unsigned long dbFixedBinary::fieldLen() const
- {
- return mBodyLength;
- }
-
-
- dbFixedBinary& dbFixedBinary::operator=(dbFixedBinary& rhs)
- {
- if (this == &rhs) // MUST use this form to avoid invoking the operator== used for searches
- return *this;
-
- setValue(rhs.binaryContents());
- return *this;
- }
-
-
- dbFixedBinary& dbFixedBinary::operator=(const char* str)
- {
- assert(strlen(str) <= mBodyLength);
- setValue(str);
- return *this;
- }
-
-
-
- void dbFixedBinary::setValue(const void* str)
- {
- validateContextInCaseRelated();
- char *writeTo = (char*)mBackend->getFieldWriteDest(mFieldNumber);
- if (writeTo) {
- memcpy(writeTo, str, mBodyLength);
- #ifdef OOF_SmartHeap
- MemPoolCheck(MemDefaultPool);
- #endif
- }
- else
- ; // error NOT YET IMPLEMENTED
- mBackend->markDirty();
- }
-
-
- void dbFixedBinary::setByte(char c, unsigned int offset)
- {
- validateContextInCaseRelated();
- char *writeTo = (char*) mBackend->getFieldWriteDest(mFieldNumber);
- if (writeTo) {
- writeTo[offset] = c;
- #ifdef OOF_SmartHeap
- MemPoolCheck(MemDefaultPool);
- #endif
- }
- else
- ; // error NOT YET IMPLEMENTED
- mBackend->markDirty();
- }
-
-
- void dbFixedBinary::extract(ostream& os)
- {
- const char *asChars = (char*)binaryContents();
- os << hex;
- for (unsigned int i=0; i<mBodyLength; i++)
- os << asChars[i] << ' ';
- }
-
-
-
- void dbFixedBinary::generateTestData(const char *testBuf, unsigned long testBufLen)
- {
- for (unsigned int i=0; i<mBodyLength; i++) {
- char c = rand()%0xFF;
- setByte(c, i);
- }
- }
-
-
- void dbFixedBinary::describe(ostream& os)
- {
- dbField::describe(os);
- os << " and a length of : " << mBodyLength << endl;
- }
-
-
- dbFixedBinary& dbFixedBinary::operator()()
- {
- dbFixedBinary* retField = (dbFixedBinary*) GetRelatedFieldOrUs();
- return *retField;
- }
-
-
- // -------------------------------------------------------
- // d b C h a r
- // -------------------------------------------------------
- char * dbChar::copyAsChars()
- {
- char* ret = new char[mBackend->fieldDataLen(this)+1];
- assert(ret);
- strcpy(ret, (const char*)*this);
- return ret;
- }
-
- OOF_fieldTypes dbChar::fieldType() const
- {
- return charField;
- }
-
-
- bool dbChar::fieldIsBinary() const
- {
- return false;
- }
-
-
- unsigned long dbChar::fieldLen() const
- {
- return mMaxLength;
- }
-
-
- dbChar::operator const char*()
- {
- validateContextInCaseRelated();
- return (char*) mBackend->getFieldReadFrom(mFieldNumber);
- }
-
-
- #ifdef _Macintosh
- void dbChar::asStr255(Str255 s)
- {
- validateContextInCaseRelated();
- char* from = (char*) mBackend->getFieldReadFrom(mFieldNumber);
- s[0] = strlen(from);
- memcpy(s+1, from, s[0]);
- #ifdef OOF_SmartHeap
- MemPoolCheck(MemDefaultPool);
- #endif
- }
-
- void dbChar::setStr255(const Str255 s)
- {
- long charLen = s[0];
- const char* strStart = (char*) s+1;
- setChars(strStart, charLen);
- }
-
-
-
- // end of Mac-specific extra conversions
- #endif
-
-
- dbChar& dbChar::operator=(dbChar& rhs)
- {
- if (this == &rhs) // MUST use this form to avoid invoking the operator== used for searches
- return *this;
-
- *this = (const char*)rhs;
- return *this;
- }
-
-
- dbChar& dbChar::operator=(const char* str)
- {
- unsigned int charLen = strlen(str);
- if (charLen > mMaxLength)
- ; // error NOT YET IMPLEMENTED
- else
- {
- validateContextInCaseRelated();
- char *writeTo = (char*)mBackend->getFieldWriteDest(mFieldNumber);
- if (writeTo)
- strcpy(writeTo, str);
- else
- ; // error NOT YET IMPLEMENTED
- }
- mBackend->markDirty();
- return *this;
- }
-
-
-
- void dbChar::setChars(const char* str , unsigned long charLen)
- {
- assert(charLen <= mMaxLength);
- validateContextInCaseRelated();
- char *writeTo = (char*)mBackend->getFieldWriteDest(mFieldNumber);
- if (writeTo) {
- memcpy(writeTo, str, charLen);
- writeTo[charLen]='\0';
- }
- else
- ; // error NOT YET IMPLEMENTED
- mBackend->markDirty();
- }
-
-
- void dbChar::extract(ostream& os)
- {
- os << (const char*)*this;
- }
-
-
-
- bool dbChar::insert(istream& is, char fieldSep, char recSep)
- {
- // this is NOT very efficient, but it *is* safe
- if (!is.good())
- return false;
-
- const unsigned int maxLen = fieldLen();
- assert(maxLen); // brief flash of paranoia in case they get this far with a field of 0 len
- char* buildBuf = new char[maxLen+1];
- assert(buildBuf);
- unsigned int charsRead = 0;
- bool hitEndOfField = false;
- while (is.good() && (charsRead<=maxLen)) { // allow read one char past, in case it's terminator
- char c;
- is >> c;
- if ((c==fieldSep) || (c==recSep)) {
- is.putback(c); // put the separator back so the caller knows what kind we hit
- hitEndOfField = true;
- break; // OK - hit a separator
- }
- if (charsRead<maxLen)
- buildBuf[charsRead] = c;
- charsRead++;
- } // loop reading char at a time
-
- bool gotDataOK = false;
- if (hitEndOfField) // everybody happy
- gotDataOK = true;
- else { // some form of problems along the way
- if (charsRead>maxLen) {// too wide for DB field, store as short anyway
- gotDataOK = true;
- dbField::insert(is, fieldSep, recSep); // consume the remainder
- #ifdef OOF_Debug
- dbConnect::raise(ostrstream() << "dbChar::insert() of field "
- << mTable->tableName() << "." << fieldName()
- << " has filled its length of " << maxLen
- << " before reaching the end of the field"
- );
- #endif
- }
- }
-
- if (gotDataOK) {
- buildBuf[charsRead] = '\0'; // now make it into a C string!
- *this = buildBuf; // finally, assign to the record
- }
- delete[] buildBuf;
- return gotDataOK; // if general stream problem, let caller report it
- }
-
-
- void dbChar::generateTestData(const char *testBuf, unsigned long testBufLen)
- {
- unsigned long randLen = rand()%mMaxLength;
- const char *readFrom = testBuf + rand()%(testBufLen-randLen);
- setChars(readFrom, randLen);
- }
-
-
- dbQueryBinary dbChar::operator==(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::equals, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbChar::startsWith(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::startsWith, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryTrinary dbChar::between(const char* fromStr, const char* toStr) const
- {
- return dbQueryTrinary(new dbQueryField(this), dbQueryClause::between,
- new dbQueryLiteralStr(fromStr), new dbQueryLiteralStr(toStr));
- }
-
-
- dbQueryTrinary dbChar::outside(const char* fromStr, const char* toStr) const
- {
- return dbQueryTrinary(new dbQueryField(this), dbQueryClause::outside,
- new dbQueryLiteralStr(fromStr), new dbQueryLiteralStr(toStr));
- }
-
-
- dbQueryBinary dbChar::operator!=(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::notEquals, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbChar::operator<(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThan, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbChar::operator<=(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThanOrEqual, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbChar::operator>(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThan, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbChar::operator>=(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThanOrEqual, new dbQueryLiteralStr(str));
- }
-
-
- void dbChar::describe(ostream& os)
- {
- dbField::describe(os);
- os << " and a maximum length of : " << mMaxLength << endl;
- }
-
-
- dbChar& dbChar::operator()()
- {
- dbChar* retField = (dbChar*) GetRelatedFieldOrUs();
- return *retField;
- }
-
-
- // -------------------------------------------------------
- // d b T e x t
- // -------------------------------------------------------
- dbText::operator const char*()
- {
- if (!mLoaded)
- LoadField();
- if (fieldDataLen())
- return (char *)mBody;
- else
- return &OOF_String::sEmptyStr;
- }
-
-
- char * dbText::copyAsChars()
- {
- unsigned long len = mBackend->fieldDataLen(this);
- char* ret;
- if (len) {
- ret = new char[len]; // len from DB includes null
- memcpy(ret, (const char*)*this, len);
- #ifdef OOF_SmartHeap
- MemPoolCheck(MemDefaultPool);
- #endif
- }
- else {
- ret = new char[1];
- ret[0] = '\0';
- }
- return ret;
- }
-
-
- OOF_fieldTypes dbText::fieldType() const
- {
- return textField;
- }
-
-
- bool dbText::fieldIsBinary() const
- {
- return false;
- }
-
-
- dbText& dbText::operator=(dbText& rhs)
- {
- if (this == &rhs) // MUST use this form to avoid invoking the operator== used for searches
- return *this;
-
- *this = (const char*)rhs;
- return *this;
- }
-
-
- dbText& dbText::operator=(const char* str)
- {
- unsigned long charLen;
- if (str)
- charLen = strlen(str);
- else
- charLen = 0;
- if (charLen) {
- allocRoomFor(charLen+1);
- memcpy((char*)mBody, str, charLen);
- ((char*)mBody)[charLen] = '\0';
- #ifdef OOF_SmartHeap
- MemPoolCheck(MemDefaultPool);
- #endif
- SetLength(charLen+1);
- }
- else
- SetLength(0);
- mBackend->markDirty();
- mDirty = true;
- mLoaded = true;
- return *this;
- }
-
-
- void dbText::setChars(const char* str , unsigned long charLen)
- {
- if (str && charLen) {
- allocRoomFor(charLen+1);
- memcpy(mBody, str, charLen);
- #ifdef OOF_SmartHeap
- MemPoolCheck(MemDefaultPool);
- #endif
- ((char*)mBody)[charLen]='\0';
- SetLength(charLen+1);
- }
- else
- SetLength(0);
- mBackend->markDirty();
- mDirty = true;
- mLoaded = true;
- }
-
-
- void dbText::operator+=(const char* str)
- {
- unsigned long charLen = strlen(str);
- unsigned long currentFldLen = mBackend->fieldDataLen(this); // inc null
- if (charLen) {
- unsigned long newLen = currentFldLen+charLen;
- allocRoomFor(newLen);
- if (!mLoaded)
- LoadField();
- memcpy((char*)mBody+currentFldLen-1, str, charLen); // we KNOW where the null is
- ((char*)mBody)[newLen-1] = '\0';
- #ifdef OOF_SmartHeap
- MemPoolCheck(MemDefaultPool);
- #endif
- SetLength(newLen);
- mBackend->markDirty();
- mDirty = true;
-
- }
- }
-
-
- void dbText::extract(ostream& os)
- {
- os << (const char*)*this;
- }
-
-
-
- void dbText::generateTestData(const char *testBuf , unsigned long testBufLen)
- {
- unsigned long randLen = rand()%testBufLen%10240; // up to 10kb allowed in one dbText
- const char *readFrom = testBuf + rand()%(testBufLen-randLen);
- setChars(readFrom, randLen);
- }
-
-
- dbQueryBinary dbText::operator==(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::equals, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbText::operator!=(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::notEquals, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbText::operator<(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThan, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbText::operator<=(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThanOrEqual, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbText::operator>(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThan, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbText::operator>=(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThanOrEqual, new dbQueryLiteralStr(str));
- }
-
-
- dbText& dbText::operator()()
- {
- dbText* retField = (dbText*) GetRelatedFieldOrUs();
- return *retField;
- }
-
-
- // -------------------------------------------------------
- // d b B L O B
- // -------------------------------------------------------
- dbBLOB::~dbBLOB()
- {
- delete[] mBody;
- };
-
-
- OOF_fieldTypes dbBLOB::fieldType() const
- {
- return blobField;
- }
-
-
- unsigned long dbBLOB::fieldLen() const
- {
- return mBackend->blobPointerReferenceSize();
- }
-
-
- bool dbBLOB::fieldIsBlob() const
- {
- return true;
- }
-
-
- void dbBLOB::SetLength(unsigned long len)
- {
- validateContextInCaseRelated();
- mBackend->setBlobLength(mFieldNumber, len);
- }
-
-
- void dbBLOB::reset()
- {
- mDirty = false;
- mLoaded = false;
- }
-
-
-
- void* dbBLOB::orphanBody()
- {
-
- void* ret = mBody;
- reset();
- mBody = 0;
- mBodyLength = 0;
- return ret;
- }
-
-
-
- void dbBLOB::adoptBody(void* body, unsigned long bodyLen)
- {
- delete[] mBody;
- mBody = body;
- mBodyLength = bodyLen;
- mLoaded = mDirty = true;
- }
-
-
-
- void* dbBLOB::allocRoomFor(unsigned long len)
- {
- if (len > mBodyLength) {
- if (mLoaded) { // assume we must preserve the buffer
- char *newBody = new char[len];
- assert(newBody);
- if (mBody) {
- memcpy(newBody, mBody, mBodyLength);
- delete[] mBody;
- }
- mBody = newBody;
- }
- else {
- delete[] mBody;
- mBody = new char[len];
- assert(mBody);
- }
- mBodyLength = len;
- }
- #ifdef OOF_SmartHeap
- MemPoolCheck(MemDefaultPool);
- #endif
- return mBody;
- }
-
-
- void dbBLOB::LoadField()
- {
- validateContextInCaseRelated();
- mBackend->loadBlob(this);
- mLoaded = true;
- }
-
-
- dbBLOB& dbBLOB::operator()()
- {
- dbBLOB* retField = (dbBLOB*) GetRelatedFieldOrUs();
- return *retField;
- }
-
-
-
- // -------------------------------------------------------
- // d b C o m p o u n d F i e l d
- // -------------------------------------------------------
- OOF_fieldTypes dbCompoundField::fieldType() const
- {
- return compoundField;
- }
-
-
- unsigned long dbCompoundField::fieldLen() const
- {
- return mTotalLength;
- }
-
-
- bool dbCompoundField::fieldIsVirtual() const
- {
- return true;
- }
-
-
- const dbField* dbCompoundField::segment(unsigned int i) const
- {
- assert(i<mSegments.count());
- return (const dbField*) (mSegments.value(i)); // safe downcast
- }
-
-
- void dbCompoundField::addSegment(dbField& segfield) {
- assert(segfield.fieldType() != textField);
- mSegments.append(&segfield);
- mTotalLength += segfield.fieldLen();
- }
-
-
- dbQueryBinary dbCompoundField::operator==(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::equals, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbCompoundField::operator!=(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::notEquals, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbCompoundField::operator<(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThan, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbCompoundField::operator<=(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThanOrEqual, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbCompoundField::operator>(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThan, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbCompoundField::operator>=(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThanOrEqual, new dbQueryLiteralStr(str));
- }
-
-
- dbQueryBinary dbCompoundField::startsWith(const char* str) const
- {
- return dbQueryBinary(new dbQueryField(this), dbQueryClause::startsWith, new dbQueryLiteralStr(str));
- }
-
-
- void dbCompoundField::extract(ostream& os)
- {
- unsigned int numSegments = mSegments.count();
- for (unsigned int i=0; i<numSegments; i++) {
- dbField* fld = (dbField*) mSegments[i]; // safe downcast
- fld->extract(os);
- }
- }
-
-
- // -------------------------------------------------------
- // O O F I L E _ f i e l d T y p e s
- // -------------------------------------------------------
- ostream& operator<<(ostream& os, OOF_fieldTypes ft)
- {
- switch (ft) {
- case (charField) :
- os << "fixed-length chars";
- break;
-
- case (textField) :
- os << "variable-length text";
- break;
-
- case (dateField) :
- os << "date";
- break;
-
- case (shortField) :
- os << "short integer";
- break;
-
- case (uShortField) :
- os << "unsigned short integer";
- break;
-
- case (longField) :
- os << "long integer";
- break;
-
- case (uLongField) :
- os << "unsigned long integer";
- break;
-
- case (realField) :
- os << "real";
- break;
-
- case (blobField) :
- os << "binary blob";
- break;
-
- case (compoundField) :
- os << "compound";
- break;
-
- case (fixedBinaryField) :
- os << "compound";
- break;
-
- case (boolField) :
- os << "compound";
- break;
-
- }
- return os;
- }
-
-
-